#pragma once

namespace WorldWind
{
	/// <summary>
	/// The closed volume that completely contains a set of objects.
	/// </summary>
	class BoundingBox
	{
	public:
#define corners_num 8
		D3DXVECTOR3 corners[corners_num];

		/// <summary>
		/// Initializes a new instance of the <see cref= "T:WorldWind.BoundingSphere"/> class.
		/// </summary>
		/// <param name="v0"></param>
		/// <param name="v1"></param>
		/// <param name="v2"></param>
		/// <param name="v3"></param>
		/// <param name="v4"></param>
		/// <param name="v5"></param>
		/// <param name="v6"></param>
		/// <param name="v7"></param>
		BoundingBox(D3DXVECTOR3 v0, D3DXVECTOR3 v1, D3DXVECTOR3 v2, D3DXVECTOR3 v3, D3DXVECTOR3 v4, D3DXVECTOR3 v5, D3DXVECTOR3 v6, D3DXVECTOR3 v7)
		{
			corners[0] = v0;
			corners[1] = v1;
			corners[2] = v2;
			corners[3] = v3;
			corners[4] = v4;
			corners[5] = v5;
			corners[6] = v6;
			corners[7] = v7;
		}

		/// <summary>
		/// Initializes a new instance of the <see cref= "T:WorldWind.BoundingSphere"/> class
		/// from a set of lat/lon values (degrees)
		/// </summary>
		/// <param name="south"></param>
		/// <param name="north"></param>
		/// <param name="west"></param>
		/// <param name="east"></param>
		/// <param name="radius1"></param>
		/// <param name="radius2"></param>
		BoundingBox( float south, float north, float west, float east, float radius1, float radius2)
		{
			float scale = radius2 / radius1;
			corners[0] = MathEngine.SphericalToCartesian(south, west, radius1);
			D3DXVec3Scale(&corners[1],&corners[0], scale);
			corners[2] = MathEngine.SphericalToCartesian(south, east, radius1);
			D3DXVec3Scale(&corners[3],&corners[2], scale);
			corners[4] = MathEngine.SphericalToCartesian(north, west, radius1);
			D3DXVec3Scale(&corners[5],&corners[4], scale);
			corners[6] = MathEngine.SphericalToCartesian(north, east, radius1);
			D3DXVec3Scale(&corners[7],&corners[6], scale);
		}

		D3DXVECTOR3 CalculateCenter()
		{
			D3DXVECTOR3 temp,res;
			for (int i=0;i<corners_num;i++)
			{
				temp += corners[i];
			}

			D3DXVec3Scale(&res,&temp,1.0f /corners_num);
			return res;
		}

		/// <summary>
		/// Calculate the screen area (pixels) covered by the bottom of the bounding box.
		/// </summary>
		float CalcRelativeScreenArea(CameraBase camera)
		{
			D3DXVECTOR3 a = camera.Project(corners[0]);
			D3DXVECTOR3 b = camera.Project(corners[2]);
			D3DXVECTOR3 c = camera.Project(corners[6]);
			D3DXVECTOR3 d = camera.Project(corners[4]);

			D3DXVECTOR3 ab,ac,ad;
			D3DXVec3Subtract(&ab,&b,&a);
			D3DXVec3Subtract(&ac,&c,&a);
			D3DXVec3Subtract(&ad,&d,&a);
			D3DXVECTOR3 temp;
			D3DXVec3Cross(&temp,&ab,&ac);
			float tri1SqArea = D3DXVec3LengthSq(temp); 
			D3DXVec3Cross(&temp,&ad,&ac);
			float tri2SqArea = D3DXVec3LengthSq(temp);  
			// Real area = (sqrt(tri1SqArea)+sqrt(tri2SqArea))/2 but we're only interested in relative size
			return tri1SqArea + tri2SqArea; 
		}
	}
}
